﻿package com.ld.hpfs.service.impl;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import com.ld.hpfs.common.utils.DoubleUtil;
import com.ld.hpfs.common.utils.InvoiceFunctionUtil;
import com.ld.hpfs.common.utils.SplitTools;
import com.ld.hpfs.dao.SplitAndMergeMapper;
import com.ld.hpfs.pojo.IdDetail;
import com.ld.hpfs.pojo.Invoice;
import com.ld.hpfs.pojo.TaxSystemParameter;
import com.ld.hpfs.service.SplitAndMergeService;

@Service
public class SplitAndMergeServiceImpl implements SplitAndMergeService {

	private static final Logger logger = LoggerFactory
			.getLogger(SplitAndMergeServiceImpl.class);

	// 算法接口
	@Autowired
	private InvoiceFunctionUtil invoiceFunctionUtil;

	@Autowired
	private SplitAndMergeMapper splitAndMergeMapper;

	@Autowired
	private JdbcTemplate jdbcTemplate;

	/*
	 * checkMaxValue 校验相同货物:超出最大限额,限制行.
	 */
	@Override
	public int checkMaxValue(HashMap<String, Object> param) {
		int result = 0;
		try {
			String[] ids = ((String)param.get("ids")).split(",");
			String companyId = (String)param.get("companyId");
			List<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
			HashMap<String,String> hm = null;
			for(int i=0;i<ids.length;i++){
				hm = new HashMap<String, String>();
				hm.put("id", ids[i]);
				list.add(hm);
			}
			HashMap<String, Object> lhm = new HashMap<String, Object>();
			lhm.put("companyId", companyId);
			lhm.put("list", list);
			Invoice invoice = splitAndMergeMapper.checkMaxValue(lhm);
			double totalAmount = invoice.getTotalAmount();
			Integer totalLine = invoice.getTotalLine();
			TaxSystemParameter taxSystemParameter = splitAndMergeMapper
					.selectTaxSysInfoById(invoice);
			double max_amount = taxSystemParameter.getMax_amount();
			Integer max_line = taxSystemParameter.getMax_line();
			if (totalAmount > max_amount) {
				result = 1;
			} else {
				if (totalLine > max_line) {
					result = 2;
				}
			}
		} catch (Exception ex) {
			logger.error(ex.getMessage());
		}
		return result;
	}

	// 合并相同货物
	@Override
	public int mergeGoods(HashMap<String, Object> param) {
		int result = -1; 
		Connection conn = null;
		try {
			String companyId = (String) param.get("companyId");
			String ids = (String)param.get("ids");
			CallableStatement proc = null;
			conn = jdbcTemplate.getDataSource().getConnection();
			proc = conn.prepareCall("{ call sp_tax_merge_goods(?,?,?) }");
			proc.setInt(1, Integer.parseInt(companyId));
			proc.setString(2, ids);
			proc.registerOutParameter(3, Types.INTEGER);
			proc.execute();
			result = proc.getInt(3);
		} catch (SQLException e) {
			e.printStackTrace();
		}catch (Exception ex) {
			logger.error(ex.getMessage());
		}finally{
			if(conn!=null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
	          }
		}
		return result;
	}

	// 合并相同客户
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public int mergeClients(HashMap<String, Object> param){
		int result = -1; 
		Connection conn = null;
		try {
			final String companyId = (String) param.get("companyId");
		    final String ids = (String)param.get("ids");
			result  = (Integer)jdbcTemplate.execute(   
				     new CallableStatementCreator() {   
				        @Override
						public CallableStatement createCallableStatement(Connection con) throws SQLException {   
				           String storedProc = "{call sp_tax_merge_customer(?,?,?)}";// 调用的sql   
				           CallableStatement cs = con.prepareCall(storedProc);   
				           cs.setInt(1, Integer.parseInt(companyId));
				           cs.setString(2, ids);
				           cs.registerOutParameter(3, Types.INTEGER);// 注册输出参数的类型   
				           return cs;   
				        }   
				     }, new CallableStatementCallback() {   
				         @Override
						public Object doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {   
				           cs.execute();   
				           return cs.getInt(3);// 获取输出参数的值   
				     }   
			    });
//			String companyId = (String) param.get("companyId");
////			String orderByCustName=(String)param.get("orderByCustName");
//			String ids = (String)param.get("ids");
//			CallableStatement proc = null;
//			conn = jdbcTemplate.getDataSource().getConnection();
//			proc = conn.prepareCall("{ call sp_tax_merge_customer(?,?) }");
//			proc.setInt(1, Integer.parseInt(companyId));
//			proc.setString(2, ids);
//			proc.execute();
//			result = 0;
		} catch (Exception ex) {
			logger.error(ex.getMessage());
		}finally{
			if(conn!=null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
	          }
		}
		return result;
	}

	// 拆分超最大行
	@Override
	public int splitDetailLine(HashMap<String, Object> param) {
		int result = -1; 
		Connection conn = null;
		try {
			String companyId = (String) param.get("companyId");
			String ids = param.get("id").toString();
			CallableStatement proc = null;
			conn = jdbcTemplate.getDataSource().getConnection();
			proc = conn.prepareCall("{ call sp_tax_split_maxline(?,?) }");
			proc.setInt(1, Integer.parseInt(companyId));
			proc.setInt(2, Integer.parseInt(ids));
			proc.execute();
			result = 0;
		} catch (SQLException e) {
			e.printStackTrace();
		}catch (Exception ex) {
			logger.error(ex.getMessage());
		}finally{
			if(conn!=null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	// 得到手工拆分前单据明细id
	@Override
	public ArrayList<HashMap<String, Object>> getManualDetailId(
			HashMap<String, Object> param) {
		// TODO Auto-generated method stub
		return splitAndMergeMapper.getManualDetailId(param);
	}
	
	/*
	 * 手工拆分
	 * 
	 * @see
	 * com.ld.hpfs.service.SplitAndMergeService#saveSplitManual(java.util.HashMap
	 * )
	 */
	@Override
	public int saveSplitManual(HashMap<String, Object> param) {
		try {
			splitAndMergeMapper.createNewDocManual(param);// 创建新单据
			ArrayList<HashMap<String, Object>> list = (ArrayList<HashMap<String, Object>>) param.get("list");//创建detail
			if (list != null && list.size() > 0) {
				List<HashMap<String, Object>> subAddList = new ArrayList<HashMap<String, Object>>();
				for (int i = 0; i < list.size(); ++i) {
					subAddList.add(list.get(i));
					if (subAddList.size() == 5) {
						param.put("list", subAddList);
						splitAndMergeMapper.insertDetailManual(param);
						subAddList.clear();
					}
				}
				if (subAddList.size() > 0) {
					param.put("list", subAddList);
					ArrayList<HashMap<String,Object>> newdetailid = splitAndMergeMapper.insertDetailManual(param);
					for(int i = 0; i < newdetailid.size(); i++) {
						// 当票据为运输类发票时添加运输类明细
						if (param.get("type").equals("T_INV")) {
							param.put("detailIdnew", newdetailid.get(i).get("detailId"));
							splitAndMergeMapper.saveInvData(param);
						}
					}
				}
			}			
//			splitAndMergeMapper.updateDocStateToSplit(param);
 			splitAndMergeMapper.enterRelationTable(param);// 将信息填入拆分合并关系表
			return 0;
		} catch (Exception ex) {
			logger.error(ex.getMessage());
			return -1;
		}
	}

	// 拆分超过最大金额
	@Override
	public HashMap<String, Object> splitMaxAount(List<Invoice> listInvoice,boolean withTrialCalculation) {
		TaxSystemParameter taxSystemParameter = null;
		HashMap<String, Object> param = new HashMap<String, Object>();
		try {
			Invoice invoice = null;
			String head_id = "";
			String result = "";
			String message = "";
			int doc_no = 0;
			boolean merge = false;
			boolean splitMaxAmountDetail  = false;
			boolean mergeMaxAmountDetail  = false;
			List<IdDetail> details = new ArrayList<IdDetail>();
			for (int i = 0; i < listInvoice.size(); i++) {
				invoice = listInvoice.get(i);
				doc_no = invoice.getNum().length();
				int num = 0;
				details.clear();
				taxSystemParameter = splitAndMergeMapper.selectTaxSysInfoById(invoice);
				double max_amount = taxSystemParameter.getMax_amount();
				List<IdDetail> listDetail = splitAndMergeMapper.getDetailsByInvoice(invoice);
                if(withTrialCalculation){
                	splitMaxAmountDetail  = this.getSplitMaxAmountDetail(listDetail, max_amount);
				}else{
					splitMaxAmountDetail  = true;
				}
                
				if(!splitMaxAmountDetail){
					listDetail = this.sortIdDetail(listDetail);
					mergeMaxAmountDetail = getMergeMaxAmountDetail(listDetail, max_amount);
				}
				
				if (mergeMaxAmountDetail || splitMaxAmountDetail) {
					Object[] obj = this.getSplitIdDetail(max_amount,listDetail, taxSystemParameter,withTrialCalculation, result, message);
					listDetail = (List<IdDetail>) obj[0];
					result = String.valueOf(obj[1]);
					message = String.valueOf(obj[2]);
					
					if (message.equals("") || message.equals("miss")) {
						listDetail = this.sortIdDetail(listDetail);
						for(int n = 0;n<listDetail.size();n++){
							details.add(listDetail.get(n));
						}
						while (listDetail.size() > 0) {
							num++;
							if((doc_no + String.valueOf(num).length()) > 18){
								result = "单据拆分后票据号长度大于20";
								merge = true;
								break;
							}
							listDetail = this.getDocumentNoLength(listDetail,max_amount);
						}
						if(merge){
							break;
						}
					}
					
					if(message.equals("calculate")){
						result = "拆分的结果将会有尾差,是否允许有尾差拆分";
						head_id = String.valueOf(invoice.getHeadId());
						break;
					}
					
					num = 0;
					while (details.size() > 0) {
						num++;
						details = this.splitIdDetail(details,(Invoice) invoice.clone(),max_amount,num);
					}
					// 更改单据为已拆分的状态
					invoice.setDoc_status(Invoice.SPLITED);
					splitAndMergeMapper.updateInvoiceSta(invoice);
					if(!message.equals("miss")){
						result = "success";
					}
				}
			}
			param.put("result", result);
			param.put("head_id", head_id);
		} catch (Exception e) {
			logger.error("Exception:", e.getMessage());
		}
		return param;
	}
	
	//超出限额的票据明细
	private boolean getSplitMaxAmountDetail(List<IdDetail> data,double maxMoney){
		boolean upDetail = false;
		for (int i = 0; i < data.size(); i++) {
			IdDetail idDetail = data.get(i);
			if (idDetail.getPrice_way() == IdDetail.priceWay0) {
				if ((idDetail.getAmount_cur() - idDetail.getDiscount_sum()) > maxMoney) {
					upDetail = true;
					break;
				}
			} else if (idDetail.getPrice_way() == IdDetail.priceWay1) {
				if ((idDetail.getAmount_cur() - idDetail.getTax_amount() - idDetail.getDiscount_sum() + idDetail.getDiscount_tax()) > maxMoney) {
					upDetail = true;
					break;
				}
			}
		}
		return upDetail;
	}
	
	//拆分明细单据信息
	private boolean getMergeMaxAmountDetail(List<IdDetail> listDetail,double max_amount){
		//运维 Eddie Start 判定最大金额超额
		//最大的明细	
		//IdDetail idDetail=listDetail.get(listDetail.size()-1);
		double amountMax= 0;
		boolean isListOne=false;
		
		for (IdDetail idDetail : listDetail) {
			if(idDetail.getPrice_way()==IdDetail.priceWay0){
				amountMax=DoubleUtil.add(amountMax,DoubleUtil.sub(idDetail.getAmount_cur()-idDetail.getDiscount_sum()));
			}else if(idDetail.getPrice_way()==IdDetail.priceWay1){
				amountMax= DoubleUtil.add(amountMax,DoubleUtil.add(DoubleUtil.sub( DoubleUtil.sub( idDetail.getAmount_cur(),-idDetail.getDiscount_sum()),idDetail.getTax_amount()),idDetail.getDiscount_tax()));
			}
		}
		
//		if((int)idDetail.getPrice_way()==IdDetail.priceWay0){
//			amountMax = DoubleUtil.sub(idDetail.getAmount_cur(), idDetail.getDiscount_sum());
//			idDetail=listDetail.get(listDetail.size()-2);
//			amountMax=DoubleUtil.add(amountMax,DoubleUtil.sub(idDetail.getAmount_cur()-idDetail.getDiscount_sum()));
//		}else if((int)idDetail.getPrice_way()==IdDetail.priceWay1){
//			amountMax =DoubleUtil.add(DoubleUtil.sub( DoubleUtil.sub( idDetail.getAmount_cur(),idDetail.getDiscount_sum()),idDetail.getTax_amount()),idDetail.getDiscount_tax());
//			idDetail=listDetail.get(listDetail.size()-2);
//			amountMax= DoubleUtil.add(amountMax,DoubleUtil.add(DoubleUtil.sub( DoubleUtil.sub( idDetail.getAmount_cur(),-idDetail.getDiscount_sum()),idDetail.getTax_amount()),idDetail.getDiscount_tax()));
//		}
		if(amountMax > max_amount){
			isListOne = true;
		}
		//运维 Eddie End
		return isListOne;
	}
	
	//判断拆分后的单据号是否大于20
	private List<IdDetail> getDocumentNoLength(List<IdDetail> listDetail,double max_amount){
		//最大的明细	
		IdDetail idDetail=listDetail.get(0);
		double amountMax= 0;
		if(idDetail.getPrice_way()==IdDetail.priceWay0){
			amountMax = DoubleUtil.sub(idDetail.getAmount_cur(), idDetail.getDiscount_sum());
		}else if(idDetail.getPrice_way()==IdDetail.priceWay1){
			amountMax =DoubleUtil.add(DoubleUtil.sub( DoubleUtil.sub( idDetail.getAmount_cur(),idDetail.getDiscount_sum()),idDetail.getTax_amount()),idDetail.getDiscount_tax());
		}else{
			amountMax = DoubleUtil.sub(idDetail.getAmount_cur(),idDetail.getDiscount_sum());
		}
		List<IdDetail> listSplit=new ArrayList<IdDetail>();
		listSplit.add(idDetail);
		boolean isListOne=true;
		for (int i = listDetail.size()-1; i>0;i--) {
			isListOne=false;
			IdDetail vo=listDetail.get(i);
			if(vo.getPrice_way()==IdDetail.priceWay0){
				if((amountMax+(vo.getAmount_cur()-vo.getDiscount_sum()))<=max_amount){
					listSplit.add(vo);
					amountMax=DoubleUtil.add(amountMax,DoubleUtil.sub(vo.getAmount_cur()-vo.getDiscount_sum()));
					listDetail.remove(i);
					isListOne=true;
				}else{
					listDetail.remove(idDetail);
					break;
				}
			}else if(vo.getPrice_way()==IdDetail.priceWay1){
				if((amountMax+(vo.getAmount_cur()-vo.getDiscount_sum()-vo.getTax_amount()+vo.getDiscount_tax()))<=max_amount){
					listSplit.add(vo);
					amountMax= DoubleUtil.add(amountMax,DoubleUtil.add(DoubleUtil.sub( DoubleUtil.sub( vo.getAmount_cur(),-vo.getDiscount_sum()),vo.getTax_amount()),vo.getDiscount_tax()));
					listDetail.remove(i);
					isListOne=true;
				}else{
					listDetail.remove(idDetail);
					break;
				}
			}	
		}
		if(isListOne){
			if(listDetail.contains(idDetail)){
				listDetail.remove(idDetail);
			}
		}	
		return listDetail;
	}
	
	//泡泡排序 冒泡
	private List<IdDetail> sortIdDetail(List<IdDetail> list) {
		List<IdDetail> listMaxMin = new ArrayList<IdDetail>();
		double[] amount = this.getSortAmount(list);
		int priceWay = list.get(0).getPrice_way();
		for (int j = 0; j < amount.length; j++) {
			for (int i = 0; i < list.size(); i++) {
				IdDetail vo1 = list.get(i);
				if (priceWay == IdDetail.priceWay0) {
					if(DoubleUtil.isSame(DoubleUtil.formatDigitDecimal(vo1.getAmount_cur()- vo1.getDiscount_sum(),2),amount[j])){
						list.remove(i);
    					listMaxMin.add(vo1);
    					break;
					}
				} else if (priceWay == IdDetail.priceWay1) {
					if(DoubleUtil.isSame(DoubleUtil.formatDigitDecimal(vo1.getAmount_cur()- vo1.getDiscount_sum()-vo1.getTax_amount()+vo1.getDiscount_tax(),2),amount[j])){
						list.remove(i);
    					listMaxMin.add(vo1);
    					break;
					}
				}
			}
		}
		return listMaxMin;
	}

	//泡泡 获取 金额
	private double[] getSortAmount(List<IdDetail> list) {
		double[] amountD = new double[list.size()];
		int priceWay = list.get(0).getPrice_way();
		for (int i = 0; i < list.size(); i++) {
			if (priceWay == IdDetail.priceWay0) {
				amountD[i] = DoubleUtil.formatDigitDecimal((list.get(i).getAmount_cur()- list.get(i).getDiscount_sum()),2);
			} else if (priceWay == IdDetail.priceWay1) {
				amountD[i] = DoubleUtil.formatDigitDecimal((list.get(i).getAmount_cur()- list.get(i).getTax_amount()- list.get(i).getDiscount_sum()
						+ list.get(i).getDiscount_tax()),2);
			}
		}
		// 从大到小
		double temp = 0;
		for (int i = 0; i < amountD.length-1; i++) {
			for (int j = i+1; j < amountD.length; j++) {
				if (amountD[i] < amountD[j]) {
					temp = amountD[j];
					amountD[j] = amountD[i];
					amountD[i] = temp;
				}
			}
		}
		return amountD;
	}
	
	//拆分最大明细
	public Object[] getSplitIdDetail(double max_amount,List<IdDetail> listDetail,TaxSystemParameter taxSystemParameterPo,boolean withTrialCalculation,String result,String message)throws Exception{
		List<IdDetail> listIdDetailAll=new ArrayList<IdDetail>();
		Object obj[]=new Object[3];
		double amount_cur_total = 0;
		boolean isWithTrialCalculation = false;
		for (int i = 0; i < listDetail.size(); i++) {
			IdDetail idDetail=(IdDetail)listDetail.get(i).clone();
			if(idDetail.getPrice_way()==IdDetail.priceWay0){
				amount_cur_total = idDetail.getAmount_cur()-idDetail.getDiscount_sum();
			}else if(idDetail.getPrice_way()==IdDetail.priceWay1){
				amount_cur_total = idDetail.getAmount_cur()-idDetail.getDiscount_sum()-idDetail.getTax_amount()+idDetail.getDiscount_tax();
			}
			
			if(amount_cur_total > max_amount){
				List<IdDetail> listSplitDetail=this.getMaxAmountCount(idDetail, max_amount,taxSystemParameterPo,withTrialCalculation,result);
				if(listSplitDetail.size()==0){
					//现在有尾差判断拆分
					if(withTrialCalculation){
						result=idDetail.getDocument_no()+":拆分的结果将会有尾差,是否允许有尾差拆分\n";	
						message = "calculate";
					}else{
						listSplitDetail=this.getMaxAmountCount(idDetail, max_amount,taxSystemParameterPo,false,result);
						isWithTrialCalculation = true;
					}
				}
				if(!withTrialCalculation){
		    		 result= idDetail.getDocument_no()+" 尾差金额:"+SplitTools.amountMiss+" 尾差税额:"+SplitTools.taxesMiss+" 尾差折扣金额:"+SplitTools.discountAmountMiss+" 尾差折扣税额:"+SplitTools.discountTaxesMiss;
		    		 isWithTrialCalculation = false;
		    		 message = "miss";
				}
				listIdDetailAll.addAll(listSplitDetail);
			}else{
				listIdDetailAll.add(idDetail);
			}
		}
		obj[0]=listIdDetailAll;
		obj[1]=result;
		obj[2]=message;
		return obj;
	}
	
	 //得到拆分的数量
	private List<IdDetail> getMaxAmountCount(IdDetail idDetail,double maxMoney,TaxSystemParameter taxSystemParameterPo,boolean withTrialCalculation,String result)throws Exception{
		List<Double> listData=new ArrayList<Double>();
				
		//splitMethod 0  按数量
		//splitMethod 1  按单价
		double taxMiss = 0.0;
		short splitMethod = taxSystemParameterPo.getCalc_rule();
//		if((idDetail.getSplitMethod()==null?(short)0:idDetail.getSplitMethod())==IdDetail.splitMethod0){
		if(splitMethod==IdDetail.splitMethod0){
			SplitTools splitToos=new SplitTools(taxSystemParameterPo.getMax_amount(),false,taxSystemParameterPo.getMinimun_line());
    		listData=splitToos.getSplitNumbers(idDetail.getDocument_no(),listData, taxSystemParameterPo.getSplit_precision(), taxSystemParameterPo.getSplit_step(), idDetail.getPrice_cur(),
    				idDetail.getQuantity(), idDetail.getTax_rate(),idDetail.getAmount_cur(),idDetail.getTax_amount(), idDetail.getDiscount_rate(),idDetail.getDiscount_sum(),(int)idDetail.getPrice_way(),withTrialCalculation);
    		taxMiss = splitToos.detailTaxesMissSum;
//		}else if(idDetail.getSplitMethod()==IdDetail.splitMethod1){
		}else if(splitMethod==IdDetail.splitMethod1){
			SplitTools splitToos=new SplitTools(taxSystemParameterPo.getMax_amount(),true,taxSystemParameterPo.getMinimun_line());
			listData=splitToos.getSplitNumbers(idDetail.getDocument_no().toString(),listData, taxSystemParameterPo.getSplit_precision(), taxSystemParameterPo.getSplit_step(), idDetail.getPrice_cur(),
    				idDetail.getQuantity(), idDetail.getTax_rate(),idDetail.getAmount_cur(),idDetail.getTax_amount(), idDetail.getDiscount_rate(),idDetail.getDiscount_sum(),(int)idDetail.getPrice_way(),withTrialCalculation);
			taxMiss = splitToos.detailTaxesMissSum;
		}
		List<IdDetail> listCount=new ArrayList<IdDetail>();
		double idDetailAmountCur = 0;
		for (int i = 0; i <listData.size(); i++) {
			IdDetail idVo=(IdDetail) idDetail.clone();
//			if((idDetail.getSplitMethod()==null?(short)0:idDetail.getSplitMethod())==IdDetail.splitMethod0){
			if(splitMethod==IdDetail.splitMethod0){
			    idDetailAmountCur=DoubleUtil.formatDigitDecimal(DoubleUtil.mul(listData.get(i),idDetail.getPrice_cur()),2);
				idVo.setAmount_cur(idDetailAmountCur);
				idVo.setQuantity(listData.get(i));
//			}else if(idDetail.getSplitMethod()==IdDetail.splitMethod1){
			}else if(splitMethod==IdDetail.splitMethod1){
			    idDetailAmountCur=DoubleUtil.formatDigitDecimal(DoubleUtil.mul(listData.get(i),idDetail.getQuantity()),2);
				idVo.setAmount_cur(idDetailAmountCur);
				idVo.setPrice_cur(listData.get(i));
			}else{
			    idDetailAmountCur=DoubleUtil.formatDigitDecimal(DoubleUtil.mul(listData.get(i),idDetail.getPrice_cur()),2);
				idVo.setAmount_cur(idDetailAmountCur);
				idVo.setQuantity(listData.get(i));
			}
			idVo.setDiscount_sum(DoubleUtil.formatDigitDecimal(DoubleUtil.mul(DoubleUtil.div(idDetail.getDiscount_sum(),idDetail.getAmount_cur()),idVo.getAmount_cur()), 2));
			//若计价是0，不含税，“折扣税额” = 上一步计算的拆分结果折扣金额×税率，保留2位小数
			//若计价是1，含税，“折扣税额” = (上一步计算的拆分结果折扣金额/1+税率)*税率，保留2位小数
			if(idDetail.getPrice_way()==IdDetail.priceWay0){
				idVo.setTax_amount(DoubleUtil.formatDigitDecimal(DoubleUtil.mul(idDetailAmountCur,idVo.getTax_rate()),2));
				idVo.setDiscount_tax(DoubleUtil.formatDigitDecimal(DoubleUtil.mul(idVo.getDiscount_sum(),idVo.getTax_rate()),2));
			}else if(idDetail.getPrice_way()==IdDetail.priceWay1){
				idVo.setTax_amount(DoubleUtil.formatDigitDecimal(DoubleUtil.mul(DoubleUtil.div(idDetailAmountCur,DoubleUtil.add(1.0, idVo.getTax_rate())), idVo.getTax_rate()),2));
				idVo.setDiscount_tax(DoubleUtil.formatDigitDecimal(DoubleUtil.mul(DoubleUtil.div(idVo.getDiscount_sum(),DoubleUtil.add(1.0, idVo.getTax_rate())),idVo.getTax_rate()),2));
//				idVo.setDiscount_tax(DoubleUtil.formatDigitDecimal(DoubleUtil.mul(idVo.getDiscount_sum(),idVo.getTax_rate()),2));
			}else{
				idVo.setTax_amount(DoubleUtil.formatDigitDecimal(DoubleUtil.mul(idDetailAmountCur,idVo.getTax_rate()),2));
				idVo.setDiscount_tax(DoubleUtil.formatDigitDecimal(DoubleUtil.mul(idVo.getDiscount_sum(),idVo.getTax_rate()),2));
			}
			//折扣处理 end
			if (!DoubleUtil.isSame(taxMiss, DoubleUtil.ZERO)) {
				idVo.setTax_amount(DoubleUtil.sub(idVo.getTax_amount(), taxMiss));
				taxMiss = DoubleUtil.ZERO;
			}
			
			listCount.add(idVo);
		}		
		return listCount;
	}
	
	//拆分明细单据信息
	private List<IdDetail> splitIdDetail(List<IdDetail> listDetail,Invoice invoice,double max_amount,int num){
		//最大的明细	
		IdDetail idDetail=listDetail.get(0);
		double amountMax= 0;
		if(idDetail.getPrice_way()==IdDetail.priceWay0){
			amountMax = DoubleUtil.sub(idDetail.getAmount_cur(), idDetail.getDiscount_sum());
		}else if(idDetail.getPrice_way()==IdDetail.priceWay1){
			amountMax =DoubleUtil.add(DoubleUtil.sub( DoubleUtil.sub( idDetail.getAmount_cur(),idDetail.getDiscount_sum()),idDetail.getTax_amount()),idDetail.getDiscount_tax());
		}else{
			amountMax = DoubleUtil.sub(idDetail.getAmount_cur(),idDetail.getDiscount_sum());
		}
		List<IdDetail> listSplit=new ArrayList<IdDetail>();
		listSplit.add(idDetail);
		boolean isListOne=true;
		for (int i = listDetail.size()-1; i>0;i--) {
			isListOne=false;
			IdDetail vo=listDetail.get(i);

			if(vo.getPrice_way()==IdDetail.priceWay0){
				if((amountMax+(vo.getAmount_cur()-vo.getDiscount_sum()))<=max_amount){
					listSplit.add(vo);
					amountMax=DoubleUtil.add(amountMax,DoubleUtil.sub(vo.getAmount_cur()-vo.getDiscount_sum()));
					listDetail.remove(i);
					isListOne=true;
				}else{
					listDetail.remove(idDetail);
					break;
				}
			}else if(vo.getPrice_way()==IdDetail.priceWay1){
				if((amountMax+(vo.getAmount_cur()-vo.getDiscount_sum()-vo.getTax_amount()+vo.getDiscount_tax()))<=max_amount){
					listSplit.add(vo);
					amountMax= DoubleUtil.add(amountMax,DoubleUtil.add(DoubleUtil.sub( DoubleUtil.sub( vo.getAmount_cur(),-vo.getDiscount_sum()),vo.getTax_amount()),vo.getDiscount_tax()));
					listDetail.remove(i);
					isListOne=true;
				}else{
					listDetail.remove(idDetail);
					break;
				}
			}	
		}
		if(isListOne){
			if(listDetail.contains(idDetail)){
				listDetail.remove(idDetail);
			}
		}	
		
		this.saveIdHeadNew(invoice, listSplit, num);
		return listDetail;
	}
	
	//保存拆分好的明细
	public void saveIdHeadNew(Invoice invoice, List<IdDetail> listSplit, int num){
		// 设置此次拆分的分隔号
		String idheadNum = invoice.getNum();
		String idheadNumNew = idheadNum + Invoice.isMaxAmount + num;
		invoice.setNum(idheadNumNew);
		invoice.setOrignal_doc_no(idheadNum);
		invoice.setTotalLine(listSplit.size());
		splitAndMergeMapper.saveInvoice(invoice);
		//存入关系表
		HashMap<String, Object> param =  new HashMap<String, Object>();
		param.put("companyId", invoice.getCompanyId());
		param.put("newDocNo", idheadNumNew);
		param.put("docNo", idheadNum);
		splitAndMergeMapper.insertRelationTable(param);
		Integer pkId = splitAndMergeMapper.getInvoiceHeadId(invoice);
		invoice.setHeadId(pkId);
		//累积明细不含税额
		double idDetailAmount=0;
		//累积明细税额
		double idDetailTaxAmount=0;
		for (int i = 0; i < listSplit.size();i++) {
			IdDetail tid = (IdDetail)listSplit.get(i).clone();
			tid.setGoods_line(i + 1);
			tid.setHeadId(pkId);
			tid.setDocument_no(idheadNumNew);
			//price_way = 0 时，amount_cur - discount_sum 汇总到 amount_cur_total，tax_amount - discount_tax 汇总到tax_amount
			//price_way = 1 时，amount_cur - discount_sum - tax_amount + discount_tax 汇总到 amount_cur_total，tax_amount - discount_tax 汇总到tax_amount
			if(tid.getPrice_way()==IdDetail.priceWay0){
				idDetailAmount = DoubleUtil.add(idDetailAmount,DoubleUtil.sub(tid.getAmount_cur(),tid.getDiscount_sum())) ;
				idDetailTaxAmount = DoubleUtil.add(idDetailTaxAmount,DoubleUtil.sub(tid.getTax_amount(),tid.getDiscount_tax()));
			}else if(tid.getPrice_way()==IdDetail.priceWay1){
				idDetailAmount = DoubleUtil.add(idDetailAmount, DoubleUtil.add(DoubleUtil.sub(DoubleUtil.sub(tid.getAmount_cur(),tid.getDiscount_sum()),tid.getTax_amount())), tid.getDiscount_tax());
				idDetailTaxAmount = DoubleUtil.add(idDetailTaxAmount,DoubleUtil.sub(tid.getTax_amount(), tid.getDiscount_tax()));
			}
			
//			//格式化小数位
			tid.setTax_amount(DoubleUtil.formatDigitDecimal(String.valueOf(tid.getTax_amount())==""?0:tid.getTax_amount(),2));
			tid.setAmount_cur(DoubleUtil.formatDigitDecimal(String.valueOf(tid.getAmount_cur())==""?0:tid.getAmount_cur(),2));
			
			int detailIdnew = splitAndMergeMapper.saveIdDetail(tid);
			String type = invoice.getType();
			if (type.equals("T_INV")) {
				HashMap<String, Object> paramForINV = new HashMap<String, Object>();
				int detailIdbefore = tid.getDetailId();
				paramForINV.put("detailIdnew", detailIdnew);
				paramForINV.put("detailIdbefore", detailIdbefore);
				// 保存交通类发票明细信息
				splitAndMergeMapper.saveInvData(paramForINV);
			}
		}
		invoice.setTotalAmount(DoubleUtil.formatDigitDecimal(idDetailAmount,2));
		invoice.setTotalTax(DoubleUtil.formatDigitDecimal(idDetailTaxAmount,2));
		splitAndMergeMapper.updateInvoice(invoice);
	}

	
	@Override
	public List<Invoice> getInvoiceById(HashMap<String, Object> param) {
		return splitAndMergeMapper.getInvoiceById(param);
	}

	@Override
	public ArrayList<HashMap<String, Object>> orderByCustName(HashMap<String, Object> param) {
		return splitAndMergeMapper.orderByCustName(param);
	}
	@Override
	public int updateDocStateToSplit(HashMap<String, Object> param) {
		try{
	    	splitAndMergeMapper.updateDocStateToSplit(param);
	    	return 0;
		}catch (Exception ex) {
			logger.error(ex.getMessage());
			return -1;
		}
	}

	@Override
	public int revokeSplitMerge(HashMap<String, Object> param) {
		// TODO Auto-generated method stub
		int result = -1; 
		Connection conn = null;
		try {
			String com_Id = (String) param.get("com_Id");
			String doc_no = (String)param.get("doc_no");
			CallableStatement proc = null;
			conn = jdbcTemplate.getDataSource().getConnection();
			proc = conn.prepareCall("{ call sp_tax_undo_reproduce(?,?) }");
			proc.setInt(1, Integer.parseInt(com_Id));
			proc.setString(2, doc_no);
			proc.execute();
			result = 0;
		}catch (Exception ex) {
			logger.error(ex.getMessage());
		}finally{
			if(conn!=null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
	          }
		}
		return result;
	}
   /*
    * Jason.Lee
    * 按ByOrigiDocNo排序
    */
	@Override
	public ArrayList<HashMap<String, Object>> orderByOrigiDocNo(
			HashMap<String, Object> param) {
		// TODO Auto-generated method stub
		return splitAndMergeMapper.orderByOrigiDocNo(param);
	}
    /*
     * by Jason.Lee
     * 从TAX_C_DOC_OPTIONS中的到One_touch_make
     */
	@Override
	public String getOneTouchMake(HashMap<String, Object> param) {
		// TODO Auto-generated method stub
		return splitAndMergeMapper.getOneTouchMake(param);
	}


	@Override
	public ArrayList<HashMap<String, Object>> getBrotherDoc(
			HashMap<String, Object> param) {
		// TODO Auto-generated method stub
		return splitAndMergeMapper.getBrotherDoc(param);
	}

	@Override
	public ArrayList<HashMap<String, Object>> getBrotherId(
			HashMap<String, Object> param) {
		// TODO Auto-generated method stub
		return splitAndMergeMapper.getBrotherId(param);
	}

	@Override
	public void setAuditedVoucher(HashMap<String, Object> param) {
		// TODO Auto-generated method stub
		splitAndMergeMapper.setAuditedVoucher(param);
		
	}


/*
* mergePostAndNegative合并正负数
* 2013.05.17  BY guxiaoli 
*/	
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public int mergePostAndNegative(HashMap<String, Object> param) {
		int result = -1; 
		Connection conn = null;
		try {
			final String companyId = (String) param.get("companyId");
			final String idA = (String)param.get("idA");
			final String idB = (String)param.get("idB");
			
			result  = (Integer)jdbcTemplate.execute(   
				     new CallableStatementCreator() {   
				        @Override
						public CallableStatement createCallableStatement(Connection con) throws SQLException {   
				           String storedProc = "{call sp_tax_merge_negative(?,?,?,?,?)}";// 调用的sql   
				           CallableStatement cs = con.prepareCall(storedProc);   
				           cs.setInt(1, Integer.parseInt(companyId));
				           cs.setString(2, idA);
				           cs.setString(3, idB);
				           cs.setInt(4, 0);// 设置输入参数的值   
				           cs.registerOutParameter(5, Types.INTEGER);// 注册输出参数的类型   
				           return cs;   
				        }   
				     }, new CallableStatementCallback() {   
				         @Override
						public Object doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {   
				           cs.execute();   
				           return cs.getInt(5);// 获取输出参数的值   
				     }   
			    });
		}catch (Exception ex) {
			logger.error(ex.getMessage());
		}finally{
			if(conn!=null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
	          }
		}
		return result;

}

/*
 * generateDiscount生成折扣
 * 2013.05.17  BY guxiaoli 
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public int generateDiscount(HashMap<String, Object> param) {
		int result = -1; 
		Connection conn = null;
		try {
			final String companyId = (String) param.get("companyId");
			final String idA = (String)param.get("idA");
			final String idB = (String)param.get("idB");
			
			result  = (Integer)jdbcTemplate.execute(   
				     new CallableStatementCreator() {   
				        @Override
						public CallableStatement createCallableStatement(Connection con) throws SQLException {   
				           String storedProc = "{call sp_tax_merge_negative(?,?,?,?,?)}";// 调用的sql   
				           CallableStatement cs = con.prepareCall(storedProc);   
				           cs.setInt(1, Integer.parseInt(companyId));
				           cs.setString(2, idA);
				           cs.setString(3, idB);
				           cs.setInt(4, 1);// 设置输入参数的值   
				           cs.registerOutParameter(5, Types.INTEGER);// 注册输出参数的类型   
				           return cs;   
				        }   
				     }, new CallableStatementCallback() {   
				         @Override
						public Object doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {   
				           cs.execute();   
				           return cs.getInt(5);// 获取输出参数的值   
				     }   
			    });
		}catch (Exception ex) {
			logger.error(ex.getMessage());
		}finally{
			if(conn!=null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
	          }
		}
		return result;
}

/*
 * 合并明细
 * @see com.ld.hpfs.service.SplitAndMergeService#mergeDetails(java.util.HashMap)
 */
@SuppressWarnings("unchecked")
@Override
public int mergeDetails(HashMap<String, Object> param) {
 	int result = -1; 
	Connection conn = null;
	try {				
		final String idx = param.get("idx").toString();
		final Integer cpn_id = Integer.parseInt(param.get("cpn_id").toString());
		final String quantity = param.get("quantity").toString();
		final String price_cur = param.get("price_cur").toString();
		final String goods_name = param.get("goods_name").toString();
		final String spec = param.get("spec").toString();
		final String goods_unit = param.get("goods_unit").toString();
		final String tax_item = param.get("tax_item").toString();
		final String discount_rate = param.get("discount_rate").toString();
		final String quantity_val = param.get("quantity_val").toString();
		final String price_cur_val = param.get("price_cur_val").toString();
		final String goods_name_val = param.get("goods_name_val").toString();
		final String spec_val = param.get("spec_val").toString();
		final String goods_unit_val = param.get("goods_unit_val").toString();
		final String tax_item_val = param.get("tax_item_val").toString();
		result  = (Integer)jdbcTemplate.execute(   
			     new CallableStatementCreator() {   
			        @Override
					public CallableStatement createCallableStatement(Connection con) throws SQLException {   
			           String storedProc = "{call sp_tax_merge_details(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}";// 调用的sql   
			           CallableStatement cs = con.prepareCall(storedProc);   
			           cs.setString(1, idx);
			           cs.setInt(2, cpn_id);
			           cs.setString(3, quantity);
			           cs.setString(4, price_cur);
			           cs.setString(5, goods_name);
			           cs.setString(6, spec);
			           cs.setString(7, goods_unit);
			           cs.setString(8, tax_item);
			           cs.setString(9, discount_rate);
			           cs.setString(10, quantity_val);
			           cs.setString(11, price_cur_val);
			           cs.setString(12, goods_name_val);
			           cs.setString(13, spec_val);
			           cs.setString(14, goods_unit_val);
			           cs.setString(15, tax_item_val);// 设置输入参数的值   
			           cs.registerOutParameter(16, Types.INTEGER);// 注册输出参数的类型   
			           return cs;   
			        }   
			     }, new CallableStatementCallback() {   
			         @Override
					public Object doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {   
			           cs.execute();   
			           return cs.getInt(16);// 获取输出参数的值   
			     }   
		    });
	}catch (Exception ex) {
		logger.error(ex.getMessage());
	}finally{
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
          }
	}
 	return result;
}



}
